package com.atguigu.srb.common.utils;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * HTTP请求工具类
 * 提供GET和POST方式的HTTP请求功能
 */
@Slf4j
public final class HttpUtils {

    private static final String POST = "POST";
    private static final String GET = "GET";
    private static final int CONN_TIMEOUT = 30000; // 连接超时时间，单位毫秒
    private static final int READ_TIMEOUT = 30000; // 读取超时时间，单位毫秒

    // 私有构造函数，防止实例化
    private HttpUtils() {
    }

    /**
     * 发送POST请求
     *
     * @param url     请求URL
     * @param reqData 请求数据
     * @return 响应字节数组，请求失败时返回null
     */
    public static byte[] doPost(String url, byte[] reqData) {
        return send(url, POST, reqData);
    }

    /**
     * 发送GET请求
     *
     * @param url 请求URL
     * @return 响应字节数组，请求失败时返回null
     */
    public static byte[] doGet(String url) {
        return send(url, GET, null);
    }

    /**
     * 发送HTTP请求
     *
     * @param url     请求URL
     * @param method  请求方法（GET/POST）
     * @param reqData 请求数据，GET请求时可为null
     * @return 响应字节数组，请求失败时返回null
     */
    public static byte[] send(String url, String method, byte[] reqData) {
        if (url == null || url.isEmpty()) {
            log.error("请求URL不能为空");
            return null;
        }

        if (method == null || (!GET.equalsIgnoreCase(method) && !POST.equalsIgnoreCase(method))) {
            log.error("不支持的请求方法: {}", method);
            return null;
        }

        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;

        try {
            // 创建URL连接
            URL requestUrl = new URL(url);
            connection = (HttpURLConnection) requestUrl.openConnection();

            // 配置连接参数
            connection.setRequestMethod(method);
            connection.setDoOutput(POST.equalsIgnoreCase(method));
            connection.setDoInput(true);
            connection.setUseCaches(false);
            connection.setInstanceFollowRedirects(true);
            connection.setConnectTimeout(CONN_TIMEOUT);
            connection.setReadTimeout(READ_TIMEOUT);

            // 建立连接
            connection.connect();

            // 处理POST请求数据
            if (POST.equalsIgnoreCase(method) && reqData != null) {
                outputStream = connection.getOutputStream();
                outputStream.write(reqData);
                outputStream.flush();
            }

            // 获取响应状态码
            int responseCode = connection.getResponseCode();

            // 根据状态码获取输入流
            if (responseCode >= 200 && responseCode < 300) {
                inputStream = connection.getInputStream();
            } else {
                inputStream = connection.getErrorStream();
                log.warn("HTTP请求返回非成功状态码: {}", responseCode);
            }

            // 读取响应数据
            if (inputStream != null) {
                return readInputStream(inputStream);
            } else {
                log.error("无法获取响应输入流，状态码: {}", responseCode);
                return null;
            }

        } catch (Exception e) {
            log.error("HTTP请求发生异常: {}", e.getMessage(), e);
            return null;
        } finally {
            // 关闭资源
            closeQuietly(outputStream);
            closeQuietly(inputStream);
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    /**
     * 从输入流中读取数据
     *
     * @param inputStream 输入流
     * @return 字节数组
     * @throws IOException 读取过程中发生的IO异常
     */
    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            return outputStream.toByteArray();
        }
    }

    /**
     * 安静地关闭Closeable资源，忽略可能的异常
     *
     * @param closeable 可关闭的资源
     */
    private static void closeQuietly(Closeable closeable) {
        if (closeable != null) {
            try {
                closeable.close();
            } catch (IOException e) {
                log.debug("关闭资源时发生异常", e);
            }
        }
    }
}